package cz.mpelant.msoe.mealchecker;

import java.io.BufferedReader;
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Date;
import java.util.List;
import java.util.Scanner;

import android.content.Context;
import android.os.Bundle;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ArrayAdapter;
import android.widget.ListView;
import android.widget.TextView;
import android.widget.Toast;
import cz.mpelant.msoe.mealchecker.data.HistoryRow;
import cz.mpelant.msoe.mealchecker.data.Plan;
import cz.mpelant.msoe.mealchecker.downloader.DownloadListener;
import cz.mpelant.msoe.mealchecker.downloader.DownloadRequest;
import cz.mpelant.msoe.mealchecker.downloader.DownloadResult;
import cz.mpelant.msoe.mealchecker.parser.HistoryParser;
import cz.mpelant.msoe.mealchecker.request.RequestHistory;
import cz.mpelant.msoe.mealchecker.request.RequestLogin;

public class HistoryActivity extends BaseActivity {
	public static final String EXTRA_PLAN = "plan";
	private static final String DOWNLOAD_LOGIN = "login";
	private static final String DOWNLOAD_HISTORY = "history";
	private Plan plan;
	private TextView txtUpdated;
	private ListView list;
	private List<HistoryRow> rows;
	private boolean loginTried;
	private boolean downloadTried;

	private DownloadListener downloadListener = new DownloadListener() {

		@Override
		public void onDownloadStarted(DownloadRequest request, Context ctx) {
			Log.v("meal", "downloading " + request.getId() + " started");

		}

		@Override
		public void onProgressUpdate(DownloadResult progress, Context ctx) {
			Log.v("meal", "downloading " + progress.getRequest().getId() + ": " + progress.getProgress() + "%");

		}

		@Override
		public void onDownloadFinished(DownloadResult status, Context ctx) {

			if (status.getProgress() != DownloadResult.DOWNLOAD_FINISHED) {
				Log.w("meal", "download not finished, interrupting...");
				return;
			}
			Log.d("meal", status.getRequest().getId() + " finished with status code " + status.getHttpResponse().getStatusLine().getStatusCode());
			if (status.getRequest().getId().equals(DOWNLOAD_HISTORY)) {
				try {
					if (isLoginSuccessful(getCacheFile(plan.code))) {
						displayHistory(getCacheFile(plan.code));
						storeFileFromCache(plan.code);
					} else {
						if (!loginTried) {
							login(DOWNLOAD_LOGIN);
							loginTried = true;
						} else
							Toast.makeText(HistoryActivity.this, R.string.error_login, Toast.LENGTH_SHORT).show();

					}
				} catch (IOException e) {
					Toast.makeText(HistoryActivity.this, R.string.error_io, Toast.LENGTH_SHORT).show();
				} catch (IllegalStateException e) {
					if (!downloadTried) {
						downloadHistory();
					} else {
						Toast.makeText(HistoryActivity.this, R.string.error_parse, Toast.LENGTH_SHORT).show();
						e.printStackTrace();
					}
				}
			}
			if (status.getRequest().getId().equals(DOWNLOAD_LOGIN)) {
				downloadHistory();
			}

		}

	};

	private class HistoryAdapter extends ArrayAdapter<HistoryRow> {

		private LayoutInflater mInflater;
		private int textViewResourceId;

		public HistoryAdapter(Context context, int textViewResourceId, List<HistoryRow> objects) {
			super(context, textViewResourceId, objects);
			this.textViewResourceId = textViewResourceId;
			this.mInflater = LayoutInflater.from(context);
		}

		class ViewHolder {
			TextView date;
			TextView location;
			TextView plan;
			TextView amount;
		}

		@Override
		public View getView(int position, View convertView, ViewGroup parent) {

			ViewHolder holder;
			View rowView = convertView;
			if (rowView == null) {
				holder = new ViewHolder();
				rowView = mInflater.inflate(textViewResourceId, null, true);
				holder.date = (TextView) rowView.findViewById(R.id.date);
				holder.location = (TextView) rowView.findViewById(R.id.location);
				holder.plan = (TextView) rowView.findViewById(R.id.plan);
				holder.amount = (TextView) rowView.findViewById(R.id.amount);
				rowView.setTag(holder);
			} else {
				holder = (ViewHolder) rowView.getTag();
			}

			HistoryRow row = getItem(position);
			holder.date.setText(row.date);
			holder.location.setText(row.location);
			if (plan.code.equals(RequestHistory.ALL))
				holder.plan.setText(row.account + " (" + row.type + ")");
			else
				holder.plan.setVisibility(View.GONE);

			holder.amount.setText(row.amount);
			if (row.amount.contains("-"))
				holder.amount.setTextColor(getResources().getColor(R.color.red));
			else
				holder.amount.setTextColor(getResources().getColor(R.color.green));

			return rowView;
		}

	}

	private HistoryAdapter adapter;

	@Override
	protected void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		setContentView(R.layout.history);
		if (!getIntent().hasExtra(EXTRA_PLAN) || (plan = (Plan) getIntent().getSerializableExtra(EXTRA_PLAN)) == null || plan.code == null) {
			finish();
			return;
		}

		setTitle(plan.name);
		list = (ListView) findViewById(android.R.id.list);
		txtUpdated = (TextView) findViewById(R.id.updated);
		rows = new ArrayList<HistoryRow>();
		adapter = new HistoryAdapter(this, R.layout.history_row, rows);
		list.setAdapter(adapter);
		try {
			displayHistory(getInternalFile(plan.code));
		} catch (Exception e) {
		}

		downloadHistory();

	}

	private void displayHistory(File f) throws IllegalStateException, IOException {

		try {
			String source = readFileAsString(f);
			String table = HistoryParser.getTable(HistoryParser.getData(source));
			String[] rows = HistoryParser.getRows(table);
			this.rows.clear();
			for (int i = 1; i < rows.length; i++) {
				try {
					HistoryRow r = HistoryParser.getRow(rows[i]);
					if (r == null)
						continue;
					this.rows.add(r);
				} catch (Exception e) {
					Log.e("meal", rows[i]);
				}

			}
			Collections.reverse(this.rows);
			adapter.notifyDataSetChanged();
			txtUpdated.setText(new Date(f.lastModified()).toLocaleString());

		} catch (IOException e) {
			e.printStackTrace();
			throw e;
		}
	}

	private void login(String ID) {
		Log.w("meal", "logging in");
		RequestLogin r = new RequestLogin(this);
		downloader.download(new DownloadRequest(r.getHttpRequest(), new ByteArrayOutputStream(), ID), downloadListener);
	}

	private boolean isLoginSuccessful(File f) throws FileNotFoundException {
		FileInputStream fis = null;
		BufferedReader br = null;
		Scanner s = null;
		try {
			fis = new FileInputStream(f);
			br = new BufferedReader(new InputStreamReader(fis));
			s = new Scanner(fis);
			return s.findWithinHorizon("TRANSACTION HISTORY", 0) != null;
		} finally {
			try {
				s.close();
				br.close();
				fis.close();
			} catch (Exception e2) {
				e2.printStackTrace();
			}

		}

	}

	@Override
	protected void refresh() {
		downloadHistory();
	}

	@Override
	protected void downloadFinished() {
		try {
			displayHistory(getInternalFile(plan.code));
		} catch (Exception e) {
		}
	}

	private void downloadHistory() {
		File f = getCacheFile(plan.code);
		RequestHistory r = new RequestHistory(this, plan.code);
		try {
			downloader.download(new DownloadRequest(r.getHttpRequest(), new FileOutputStream(f), DOWNLOAD_HISTORY), downloadListener);
		} catch (FileNotFoundException e) {
			e.printStackTrace();
		}
	}
}
